package start.spring.basic.flowable.service.applyrecord.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;

import start.spring.basic.constant.CommonConstant;
import start.spring.basic.flowable.config.FlowableContextHolder;
import start.spring.basic.flowable.dao.WfApplyRecordMapper;
import start.spring.basic.flowable.entity.WfApplyRecord;
import start.spring.basic.flowable.enums.flowable.ApprovalStatus;
import start.spring.basic.flowable.service.BaseServiceImpl;
import start.spring.basic.flowable.service.IFlowableBaseService;
import start.spring.basic.flowable.service.applyrecord.IWfApplyRecordService;
import start.spring.basic.flowable.service.process.IWfProcessService;
import start.spring.basic.page.PageQuery;
import start.spring.basic.page.PageResult;
import start.spring.basic.response.ResponseData;
import start.spring.basic.util.common.StringUtil;

/**
 * 我的流程Service业务层处理
 * 
 * @author csc
 * @date 2023-12-09
 */
@Service
public class WfApplyRecordServiceImpl extends BaseServiceImpl implements IWfApplyRecordService {
    
    @Autowired
    private WfApplyRecordMapper wfApplyRecordMapper;
    
    @Autowired
    private FlowableContextHolder flowableContextHolder;
    
    @Autowired
    private IWfProcessService wfProcessService;

    /**
     * 查询我的流程列表
     * 
     * @param wfApplyRecord 我的流程
     * @return 我的流程
     */
    @Override
    public PageResult<WfApplyRecord> selectWfApplyRecordPageList(PageQuery pageQuery,WfApplyRecord wfApplyRecord) {
        IPage<WfApplyRecord> page = super.getPage(pageQuery);
        QueryWrapper<WfApplyRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(WfApplyRecord::getUserId, super.getSysUser().getUserId());
        queryWrapper.lambda().like(!StringUtil.isEmpty(wfApplyRecord.getDefinitionName()), WfApplyRecord::getDefinitionName, wfApplyRecord.getDefinitionName());
    	queryWrapper.lambda().eq(!StringUtil.isEmpty(wfApplyRecord.getApprovalStatus()), WfApplyRecord::getApprovalStatus, wfApplyRecord.getApprovalStatus());
        if(!StringUtil.isEmpty(wfApplyRecord.getBeginApplyTime()) && !StringUtil.isEmpty(wfApplyRecord.getEndApplyTime())) {
        	queryWrapper.lambda().between(WfApplyRecord::getApplyTime, wfApplyRecord.getBeginApplyTime() + CommonConstant.SURFIX_DATE_BEGIN, wfApplyRecord.getEndApplyTime() + CommonConstant.SURFIX_DATE_END);
        }
        if(!StringUtil.isEmpty(wfApplyRecord.getBeginApprovalCompleteTime()) && !StringUtil.isEmpty(wfApplyRecord.getEndApprovalCompleteTime())) {
        	queryWrapper.lambda().between(WfApplyRecord::getApprovalCompleteTime, wfApplyRecord.getBeginApprovalCompleteTime() + CommonConstant.SURFIX_DATE_BEGIN, wfApplyRecord.getEndApprovalCompleteTime() + CommonConstant.SURFIX_DATE_END);
        }
        queryWrapper.lambda().orderByDesc(WfApplyRecord::getApplyTime);
        page = this.wfApplyRecordMapper.selectPage(page, queryWrapper);
        return super.getPageResult(page);
    }
    
    /**
     * 查询全量我的流程
     * 
     * @param wfApplyRecord 我的流程
     * @return 我的流程
     */
    @Override
    public List<WfApplyRecord> selectWfApplyRecordList(WfApplyRecord wfApplyRecord) {
    	QueryWrapper<WfApplyRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(WfApplyRecord::getUserId, super.getSysUser().getUserId());
        queryWrapper.lambda().like(!StringUtil.isEmpty(wfApplyRecord.getDefinitionName()), WfApplyRecord::getDefinitionName, wfApplyRecord.getDefinitionName());
    	queryWrapper.lambda().eq(!StringUtil.isEmpty(wfApplyRecord.getApprovalStatus()), WfApplyRecord::getApprovalStatus, wfApplyRecord.getApprovalStatus());
        if(!StringUtil.isEmpty(wfApplyRecord.getBeginApplyTime()) && !StringUtil.isEmpty(wfApplyRecord.getEndApplyTime())) {
        	queryWrapper.lambda().between(WfApplyRecord::getApplyTime, wfApplyRecord.getBeginApplyTime() + CommonConstant.SURFIX_DATE_BEGIN, wfApplyRecord.getEndApplyTime() + CommonConstant.SURFIX_DATE_END);
        }
        if(!StringUtil.isEmpty(wfApplyRecord.getBeginApprovalCompleteTime()) && !StringUtil.isEmpty(wfApplyRecord.getEndApprovalCompleteTime())) {
        	queryWrapper.lambda().between(WfApplyRecord::getApprovalCompleteTime, wfApplyRecord.getBeginApprovalCompleteTime() + CommonConstant.SURFIX_DATE_BEGIN, wfApplyRecord.getEndApprovalCompleteTime() + CommonConstant.SURFIX_DATE_END);
        }
        queryWrapper.lambda().orderByDesc(WfApplyRecord::getApplyTime);
        return this.wfApplyRecordMapper.selectList(queryWrapper);
    }

    /**
     * 新增我的流程
     * 
     * @param wfApplyRecord 我的流程
     * @return 结果
     */
    @Override
    public int insertWfApplyRecord(WfApplyRecord wfApplyRecord) {
        return this.wfApplyRecordMapper.insert(wfApplyRecord);
    }
    
    @Override
    public int updateWfApplyRecordById(WfApplyRecord wfApplyRecord) {
    	UpdateWrapper<WfApplyRecord> updateWrapper = new UpdateWrapper<>();
    	updateWrapper.lambda().eq(WfApplyRecord::getId, wfApplyRecord.getId());
        return this.wfApplyRecordMapper.update(wfApplyRecord, updateWrapper);
    }
    
    @Override
    public int updateByProcessInstanceId(WfApplyRecord wfApplyRecord) {
    	UpdateWrapper<WfApplyRecord> updateWrapper = new UpdateWrapper<>();
    	updateWrapper.lambda().eq(WfApplyRecord::getProcessInstanceId, wfApplyRecord.getProcessInstanceId());
        return this.wfApplyRecordMapper.update(wfApplyRecord, updateWrapper);
    }

    /**
     * 批量删除我的流程
     * 
     * @param ids 需要删除的我的流程主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseData<String> deleteWfApplyRecordByIds(List<String> ids) {
    	if(ids!=null&&ids.size()>0) {
    		QueryWrapper<WfApplyRecord> applyRecordQueryWrapper = new QueryWrapper<>();
        	applyRecordQueryWrapper.lambda()
        			.eq(WfApplyRecord::getUserId, super.getSysUser().getUserId())
        			.in(WfApplyRecord::getId, ids);
        	//获取需要删除的业务表记录主键
        	List<WfApplyRecord> applyRecordList = this.wfApplyRecordMapper.selectList(applyRecordQueryWrapper);
        	if(applyRecordList!=null&&applyRecordList.size()==ids.size()) {
        		
        		List<String> delFlowableList = new ArrayList<>();
        		
        		List<String> beanNameList = new ArrayList<>();
        		Map<String,List<String>> businessKeyMap = new HashMap<String,List<String>>();
        		
        		boolean canDeleteRecord = true;
        		
        		//归类业务记录主键
            	for(WfApplyRecord wfApplyRecord:applyRecordList) {
            		
            		if(ApprovalStatus.WAITING.getStatus().equals(wfApplyRecord.getApprovalStatus())
            				||ApprovalStatus.PASSED.getStatus().equals(wfApplyRecord.getApprovalStatus())
            				||ApprovalStatus.RUNNING.getStatus().equals(wfApplyRecord.getApprovalStatus())
            				||ApprovalStatus.REJECT.getStatus().equals(wfApplyRecord.getApprovalStatus())) {
            			canDeleteRecord = false;
            			break;
            		}else {
            			//可删除
            			delFlowableList.add(wfApplyRecord.getProcessInstanceId());
            		}
            		
            		List<String> businessKeyList = null;
            		String beanName = wfApplyRecord.getBeanName();
            		if(businessKeyMap.containsKey(beanName)) {
            			businessKeyList = businessKeyMap.get(beanName);
            			businessKeyList.add(wfApplyRecord.getBusinessKey());
            		}else {
            			beanNameList.add(beanName);
            			businessKeyList = new ArrayList<>();
            			businessKeyList.add(wfApplyRecord.getBusinessKey());
            		}
            		businessKeyMap.put(beanName, businessKeyList);
            	}
            	
            	if(!canDeleteRecord) {
            		return ResponseData.errorMsg("不可删除审批中及审批通过的记录!");
            	}else {
            		//删除申请记录表
                	this.wfApplyRecordMapper.delete(applyRecordQueryWrapper);
                	
                	//删除业务表，可以优化为通过kafka异步删除
                	for(String beanName:beanNameList) {
                		IFlowableBaseService flowableBaseService = flowableContextHolder.getFlowableService(beanName);
                		flowableBaseService.handleDelete(businessKeyMap.get(beanName));
                	}
                	
                	//删除工作流引擎中的记录
                	this.wfProcessService.deleteProcessByIds(delFlowableList);
                	
                	return ResponseData.successMsg("申请记录已删除!");
            	}
            	
        	}else {
        		return ResponseData.errorMsg("部分需要删除的记录已不存在，请提交正确的删除申请!");
        	}
    	}else {
    		return ResponseData.errorMsg("未查询到需要删除的记录!");
    	}
    }

	@Override
	@Transactional(rollbackFor = Exception.class)
	public ResponseData<String> revokeWfApplyRecordById(String id) {
		if(!StringUtil.isEmpty(id)) {
			QueryWrapper<WfApplyRecord> applyRecordQueryWrapper = new QueryWrapper<>();
        	applyRecordQueryWrapper.lambda()
        			.eq(WfApplyRecord::getUserId, super.getSysUser().getUserId())
        			.eq(WfApplyRecord::getId, id);
        	WfApplyRecord applyRecord = this.wfApplyRecordMapper.selectOne(applyRecordQueryWrapper);
        	if(applyRecord==null) {
        		return ResponseData.errorMsg("未查询到需要撤回的申请！");
        	}else {
        		if(ApprovalStatus.WAITING.getStatus().equals(applyRecord.getApprovalStatus())) {
        			//撤回后变为草稿状态
        			WfApplyRecord applyRecordUpdate = new WfApplyRecord();
        			applyRecordUpdate.setId(id);
        			applyRecordUpdate.setApprovalStatus(ApprovalStatus.REVOKE.getStatus());
        			applyRecordUpdate.setUpdateTime(new Date());
        			this.updateWfApplyRecordById(applyRecordUpdate);
        			
        			//删除工作流引擎中的记录
        			List<String> instanceIdList = new ArrayList<>();
        			instanceIdList.add(applyRecord.getProcessInstanceId());
        			this.wfProcessService.deleteProcessByIds(instanceIdList);
        			
        			return ResponseData.successMsg("申请已撤回，可修改后重新提交！");
        		}else {
        			return ResponseData.errorMsg("不可撤回，仅允许撤回等待审批的申请！");
        		}
        	}
		}else {
			return ResponseData.errorMsg("非法请求！");
		}
	}
	
}
